CloudFront Hosting Toolkitを使って静的Webサイト環境を作ってみた
手間をかけずにCloudFrontを使った静的Webサイトを作りたい
こんにちは、のんピ(@non____97)です。
皆さんは手間をかけずにCloudFrontを使った静的Webサイトを作りたいなと思ったことはありますか? 私はあります。
過去にAWS CDKを使ってこの思いを実現したことがありますが、一からAWS CDKを作り込むのはなかなか大変でした。
そんな苦労はCloudFront Hosting Toolkitを使用すると少し解消されるかもしれません。
CloudFront Hosting ToolkitはCLIまたはAWS CDKでフロントエンドのホスティングとCI/CDパイプラインを用意するツールです。
今だとAmplifyを使えば良いのではないか? という声も聞こえてきますが、細かいカスタマイズを行いたい場合にCloudFront周りを直接操作したい場合があります。そういったときにCloudFront Hosting Toolkitを使用すれば、素早く環境を用意することが可能です。
デプロイはGitHubリポジトリを用意し、コマンドを数回実行する程度です。これは便利です。
CloudFront Hosting Toolkitを紹介しているAWS Blogsは以下をご覧ください。
具体的な使用方法についてはGitHubをご覧ください。
実際に使ってみたので紹介します。
いきなりまとめ
- CloudFront Hosting ToolkitはCLIまたはAWS CDKでフロントエンドのホスティングとCI/CDパイプラインを用意するツール
- AWS CDKのL3 Constructとして使用することも可能
- サポートされているフロントエンドフレームワークは以下
- AngularJS
- Next.js
- React
- Vue.js
- フロントエンドフレームワークを使用しないことも可能
- カスタムドメインを割り当てることも可能
- CloudFront Hosting Toolkit v1.9時点では以下に注意
- 連携可能なGitリポジトリはGitHubのみ
- AWS CLIのプロファイルはサポートされていない
- CLI操作の場合、グローバルインストールをしなければLambda Layerに必要なパッケージがバンドルされない
CloudFront Hosting Toolkitとは
CloudFront Hosting ToolkitとはCLIまたはAWS CDKでフロントエンドのホスティングとCI/CDパイプラインを用意するツールです。
環境をデプロイした後はGitにPushするだけで自動でコンテンツをデプロイすることが可能です。
サポートされているフロントエンドフレームワークは以下のとおりです。
- AngularJS
- Next.js
- React
- Vue.js
フロントエンドフレームワークを使わないという選択肢も可能です。
現時点ではSSRはサポートされていません。ロードマップには含まれているので期待して待ちましょう。
また、連携できるGitリポジトリはGitHub上のもののみです。
カスタムドメインについては使用可能です。本番環境でも使えそうですね。
全体概要は以下のとおりです。
大半のリソースのデプロイはAWS CDKで行われています。L3 Constructとして使用することも可能です。一部分だけ組み込みたいという場面に役立ちそうですね。
Webアクセスおよびデプロイのフローについては以下の図が非常に参考になります。
CloudFront KeyValueStoreとCloudFront Functionsを用いることによって、コンテンツ更新時に新しいコンテンツにユーザーが素早くアクセスできるようにしています。
やってみた
CloudFront Hosting Toolkitのインストール
実際にやってみましょう。今回はAWS CDKではなく、CLIでデプロイします。
まず、CloudFront Hosting Toolkitのインストールをします。
GitHub上にはグローバルインストールをするように記載がありましたが、ローカルインストールで試します。
$ npm i @aws/cloudfront-hosting-toolkit npm WARN deprecated inflight@1.0.6: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. npm WARN deprecated glob@7.2.3: Glob versions prior to v9 are no longer supported npm WARN deprecated @aws-sdk/node-config-provider@3.374.0: This package has moved to @smithy/node-config-provider npm WARN deprecated @aws-sdk/config-resolver@3.374.0: This package has moved to @smithy/config-resolver added 310 packages in 17s 26 packages are looking for funding run `npm fund` for details
310パッケージと、それなりの数のパッケージがインストールされました。直接の依存パッケージはcloudfront-hosting-toolkit/package.jsonをご覧ください。
GitHubのプライベートリポジトリの用意
GitHubのプライベートリポジトリの用意をします。
CloudFront Hosting Toolkitのデプロイメントの初期化を行う際にGitHubのリポジトリのURLが必要です。
今回はcloudfront-hosting-toolkit-test
というプライベートリポジトリを用意しました。
手元の端末にクローンして、cdしておきます。
$ git clone https://github.com/non-97/cloudfront-hosting-toolkit-test.git Cloning into 'cloudfront-hosting-toolkit-test'... remote: Enumerating objects: 3, done. remote: Counting objects: 100% (3/3), done. remote: Total 3 (delta 0), reused 3 (delta 0), pack-reused 0 Receiving objects: 100% (3/3), done. $ cd cloudfront-hosting-toolkit-test/ $ ls -la total 8 drwxr-xr-x@ 4 <ユーザー名> staff 128 6 20 13:39 ./ drwxr-xr-x@ 9 <ユーザー名> staff 288 6 20 13:39 ../ drwxr-xr-x@ 11 <ユーザー名> staff 352 6 20 13:40 .git/ -rw-r--r--@ 1 <ユーザー名> staff 34 6 20 13:39 README.md
CloudFront Hosting Toolkitのデプロイメントの初期化
CloudFront Hosting Toolkitのデプロイメントの初期化を行います。
$ npx cloudfront-hosting-toolkit init --------------------- Static hosting configuration wizard : GitHub Source Code Repository Based ------------------- To facilitate the deployment of the necessary infrastructure for website hosting, certain information is required. cloudfront-hosting-toolkit will aim to find as much relevant data as possible. Collecting information about the GitHub repository from /<作業ディレクトリパス>/cloudfront-hosting-toolkit-test ? Please provide your GitHub repository URL ›
GitHubのリポジトリURLの入力を促されました。入力してあげましょう。
? Please provide your GitHub repository URL › https://github.com/non-97/cloudfront-hosting-toolkit-test.git ✔ Please provide your GitHub repository URL … https://github.com/non-97/cloudfront-hosting-toolkit-test.git ? What is the name of the branch you would like to use? Hit Enter to confirm or change the selection. › main
次にブランチ名を使用するのかを選択するようです。mainブランチを選択します。
? What is the name of the branch you would like to use? Hit Enter to confirm or change the selection. › main ✔ What is the name of the branch you would like to use? Hit Enter to confirm or change the selection. … main ? Which framework did you use for website construction? Press Enter to confirm or change the selection. › - Use arrow-keys. Return to submit. AngularJS Framework ❯ No FrontEnd framework used; Basic implementation (no build required) Next.js Framework React Framework Vue.js Framework None from the list, exit and add my own
次にWebサイトのフロントエンドのフレームワークを選択するようです。今回は特に使用しないのでNo FrontEnd framework used
を選択します。
? Which framework did you use for website construction? Press Enter to confirm or change the selection. › - Use arrow-keys. Return to submit. AngularJS Framework ❯ No FrontEnd framework used; Basic implementation (no build required) Next.js Framework React Framework Vue.js Framework None from the list, exit and add my own ✔ Which framework did you use for website construction? Press Enter to confirm or change the selection. › No FrontEnd framework used; Basic implementation (no build required) ? Do you own a domain name that you would like to use? › - Use arrow-keys. Return to submit. Yes ❯ No
次にカスタムドメインを使用するかどうかの選択です。カスタムドメインを使用したいので、Yesを選択します。
? Do you own a domain name that you would like to use? › - Use arrow-keys. Return to submit. ❯ Yes No ✔ Do you own a domain name that you would like to use? › Yes Please provide your domain name in the following formats:
ドメインの選択です。今回はcf-test.non-97.net
にします。
? Please provide your domain name in the following formats: www.mydomainname.com or mydomainname.com ? > cf-test.non-97.net ✔ Please provide your domain name in the following formats: www.mydomainname.com or mydomainname.com ? … cf-test.non-97.net ? Where is the authoritative DNS server of this domain? › - Use arrow-keys. Return to submit. Elsewhere ❯ Route 53 in this AWS Account
そのドメインをどこのDNSサーバーで管理しているか選択します。デプロイ先と同じAWSアカウント上のRoute 53 Public Hosted Zoneを使用したいのでRoute 53 in this AWS Account
を選択します。併せてcf-test.non-97.net
を管理しているRoute 53 Public Hosted ZoneのIDを入力します。
? Where is the authoritative DNS server of this domain? › - Use arrow-keys. Return to submit. Elsewhere ❯ Route 53 in this AWS Account ✔ Where is the authoritative DNS server of this domain? › Route 53 in this AWS Account ✔ Please type the hosted zone ID … Z00551472Z2MB7670X9ER ---------------------------------------------------- Here is the configuration that has been generated and saved to cloudfront-hosting-toolkit/cloudfront-hosting-toolkit-config.json file.: > GitHub repository: https://github.com/non-97/cloudfront-hosting-toolkit-test.git/main > Framework: basic > Domain name: cf-test.non-97.net > Hosted zone ID: Z00551472Z2MB7670X9ER -- > Configuration file generated /<作業ディレクトリパス>/cloudfront-hosting-toolkit-test/cloudfront-hosting-toolkit/cloudfront-hosting-toolkit-config.json > Build configuration generated /<作業ディレクトリパス>/cloudfront-hosting-toolkit-test/cloudfront-hosting-toolkit/cloudfront-hosting-toolkit-build.yml > CloudFront Function source code generated /<作業ディレクトリパス>/cloudfront-hosting-toolkit-test/cloudfront-hosting-toolkit/cloudfront-hosting-toolkit-cff.js The initialization process has been completed. You may now execute 'cloudfront-hosting-toolkit deploy' to deploy the infrastructure.
初期化が設定が完了し、設定ファイルが出力されました。
出力されたファイルは以下のとおりです。BuildspecのYAMLファイルやCloudFront Functionsと思われるJavaScriptのコードが生成されていますね。
{ "repoUrl": "https://github.com/non-97/cloudfront-hosting-toolkit-test.git", "branchName": "main", "framework": "basic", "domainName": "cf-test.non-97.net", "hostedZoneId": "Z00551472Z2MB7670X9ER" }
version: 0.2 phases: build: commands: - echo aws s3 cp ./ s3://$DEST_BUCKET_NAME/$CODEBUILD_RESOLVED_SOURCE_VERSION/ --recursive #don't change this line - aws s3 cp ./ s3://$DEST_BUCKET_NAME/$CODEBUILD_RESOLVED_SOURCE_VERSION/ --recursive #don't change this line
import cf from 'cloudfront'; const kvsId = '__KVS_ID__'; // This fails if the key value store is not associated with the function const kvsHandle = cf.kvs(kvsId); function pointsToFile(uri) { return /\/[^/]+\.[^/]+$/.test(uri); } var rulePatterns = { "/$": "/index.html", // When URI ends with a '/', append 'index.html' "!file": ".html", // When URI doesn't point to a specific file and doesn't have a trailing slash, append '.html' "!file/": "/index.html",// When URI has a trailing slash and doesn't point to a specific file, append 'index.html' }; // Function to determine rule and update the URI async function updateURI(uri) { let pathToAdd = ""; try { pathToAdd = await kvsHandle.get("path"); } catch (err) { console.log(`No key 'path' present : ${err}`); return uri; } // Check for trailing slash and apply rule. if (uri.endsWith("/") && rulePatterns["/$"]) { return "/" + pathToAdd + uri.slice(0, -1) + rulePatterns["/$"]; } // Check if URI doesn't point to a specific file. if (!pointsToFile(uri)) { // If URI doesn't have a trailing slash, apply rule. if (!uri.endsWith("/") && rulePatterns["!file"]) { return "/" + pathToAdd + uri + rulePatterns["!file"]; } // If URI has a trailing slash, apply rule. if (uri.endsWith("/") && rulePatterns["!file/"]) { return "/" + pathToAdd + uri.slice(0, -1) + rulePatterns["!file/"]; } } return "/" + pathToAdd + uri; } // Main CloudFront handler async function handler(event) { var request = event.request; var uri = request.uri; //console.log("URI BEFORE: " + request.uri); // Uncomment if needed request.uri = await updateURI(uri); //console.log("URI AFTER: " + request.uri); // Uncomment if needed return request; }
CloudFront Hosting Toolkitを使ったデプロイ
CloudFront Hosting Toolkitを使ってデプロイします。
$ aws sts get-caller-identity Enter MFA code for arn:aws:iam::<Assume Role元AWSアカウントID>:mfa/<MFAデバイス名>: { "UserId": "<IAMユーザーID>:botocore-session-1718859240", "Account": "<Assume Role先AWSアカウントID>", "Arn": "arn:aws:sts::<Assume Role先AWSアカウントID>:assumed-role/<IAMロール名>/botocore-session-1718859240" } $ npx cloudfront-hosting-toolkit deploy --> 1. Setting up a SSL/TLS certificate with AWS Certificate Manager (ACM) Error checking ACM Certificate AccessDeniedException: User: arn:aws:iam::<Assume Role元AWSアカウントID>:user/<IAMユーザー名> is not authorized to perform: acm:ListCertificates with an explicit deny in an identity-based policy at de_AccessDeniedExceptionRes (/<作業ディレクトリパス>/node_modules/@aws-sdk/client-acm/dist-cjs/index.js:986:21) at de_CommandError (/<作業ディレクトリパス>/node_modules/@aws-sdk/client-acm/dist-cjs/index.js:949:19) at process.processTicksAndRejections (node:internal/process/task_queues:95:5) at async /<作業ディレクトリパス>/node_modules/@smithy/middleware-serde/dist-cjs/index.js:35:20 at async /<作業ディレクトリパス>/node_modules/@smithy/core/dist-cjs/index.js:165:18 at async /<作業ディレクトリパス>/node_modules/@smithy/middleware-retry/dist-cjs/index.js:320:38 at async /<作業ディレクトリパス>/node_modules/@aws-sdk/middleware-logger/dist-cjs/index.js:34:22 at async checkCertificateExists (/<作業ディレクトリパス>/node_modules/@aws/cloudfront-hosting-toolkit/bin/cli/utils/awsSDKUtil.js:98:26) at async handleDeployCommand (/<作業ディレクトリパス>/node_modules/@aws/cloudfront-hosting-toolkit/bin/cli/actions/deploy.js:67:42) at async handleCommand (/<作業ディレクトリパス>/node_modules/@aws/cloudfront-hosting-toolkit/bin/cli/index.js:54:13) { '$fault': 'client', '$metadata': { httpStatusCode: 400, requestId: '386f3574-35b6-4ff2-bda4-6f54bba13849', extendedRequestId: undefined, cfId: undefined, attempts: 1, totalRetryDelay: 0 }, __type: 'AccessDeniedException' } AccessDeniedException: User: arn:aws:iam::<Assume Role元AWSアカウントID>:user/<IAMユーザー名> is not authorized to perform: acm:ListCertificates with an explicit deny in an identity-based policy at de_AccessDeniedExceptionRes (/<作業ディレクトリパス>/node_modules/@aws-sdk/client-acm/dist-cjs/index.js:986:21) at de_CommandError (/<作業ディレクトリパス>/node_modules/@aws-sdk/client-acm/dist-cjs/index.js:949:19) at process.processTicksAndRejections (node:internal/process/task_queues:95:5) at async /<作業ディレクトリパス>/node_modules/@smithy/middleware-serde/dist-cjs/index.js:35:20 at async /<作業ディレクトリパス>/node_modules/@smithy/core/dist-cjs/index.js:165:18 at async /<作業ディレクトリパス>/node_modules/@smithy/middleware-retry/dist-cjs/index.js:320:38 at async /<作業ディレクトリパス>/node_modules/@aws-sdk/middleware-logger/dist-cjs/index.js:34:22 at async checkCertificateExists (/<作業ディレクトリパス>/node_modules/@aws/cloudfront-hosting-toolkit/bin/cli/utils/awsSDKUtil.js:98:26) at async handleDeployCommand (/<作業ディレクトリパス>/node_modules/@aws/cloudfront-hosting-toolkit/bin/cli/actions/deploy.js:67:42) at async handleCommand (/<作業ディレクトリパス>/node_modules/@aws/cloudfront-hosting-toolkit/bin/cli/index.js:54:13) { '$fault': 'client', '$metadata': { httpStatusCode: 400, requestId: '386f3574-35b6-4ff2-bda4-6f54bba13849', extendedRequestId: undefined, cfId: undefined, attempts: 1, totalRetryDelay: 0 }, __type: 'AccessDeniedException' }
権限が不足しており、デプロイできないようです。
私の端末では以下記事のようにAWS CLIからAssume Roleをして操作をするように設定しています。
プロファイル名を指定しても結果は変わりありませんでした。
$ npx cloudfront-hosting-toolkit status --profile <プロファイル名> Error retrieving parameter PipelineName AccessDeniedException: User: arn:aws:iam::<Assume Role元AWSアカウントID>:user/<IAMユーザー名> is not authorized to perform: ssm:GetParameter on resource: arn:aws:ssm:us-east-1:<Assume Role元AWSアカウントID>:parameter/hosting-main-cloudfront-hosting-toolkit-test-main/PipelineName with an explicit deny in an identity-based policy at throwDefaultError (/<作業ディレクトリパス>/node_modules/@smithy/smithy-client/dist-cjs/index.js:839:20) at /<作業ディレクトリパス>/node_modules/@smithy/smithy-client/dist-cjs/index.js:848:5 at de_CommandError (/<作業ディレクトリパス>/node_modules/@aws-sdk/client-ssm/dist-cjs/index.js:7003:14) at process.processTicksAndRejections (node:internal/process/task_queues:95:5) at async /<作業ディレクトリパス>/node_modules/@smithy/middleware-serde/dist-cjs/index.js:35:20 at async /<作業ディレクトリパス>/node_modules/@smithy/core/dist-cjs/index.js:165:18 at async /<作業ディレクトリパス>/node_modules/@smithy/middleware-retry/dist-cjs/index.js:320:38 at async /<作業ディレクトリパス>/node_modules/@aws-sdk/middleware-logger/dist-cjs/index.js:34:22 at async getSSMParameter (/<作業ディレクトリパス>/node_modules/@aws/cloudfront-hosting-toolkit/bin/cli/utils/awsSDKUtil.js:499:26) at async getPipelineStatus (/<作業ディレクトリパス>/node_modules/@aws/cloudfront-hosting-toolkit/bin/cli/utils/awsSDKUtil.js:534:30) { '$fault': 'client', '$metadata': { httpStatusCode: 400, requestId: 'aaa09af6-7166-4b3d-9050-7f432ad57b05', extendedRequestId: undefined, cfId: undefined, attempts: 1, totalRetryDelay: 0 }, __type: 'AccessDeniedException' } Error getting Pipeline Status AccessDeniedException: User: arn:aws:iam::<Assume Role元AWSアカウントID>:user/<IAMユーザー名> is not authorized to perform: ssm:GetParameter on resource: arn:aws:ssm:us-east-1:<Assume Role元AWSアカウントID>:parameter/hosting-main-cloudfront-hosting-toolkit-test-main/PipelineName with an explicit deny in an identity-based policy at throwDefaultError (/<作業ディレクトリパス>/node_modules/@smithy/smithy-client/dist-cjs/index.js:839:20) at /<作業ディレクトリパス>/node_modules/@smithy/smithy-client/dist-cjs/index.js:848:5 at de_CommandError (/<作業ディレクトリパス>/node_modules/@aws-sdk/client-ssm/dist-cjs/index.js:7003:14) at process.processTicksAndRejections (node:internal/process/task_queues:95:5) at async /<作業ディレクトリパス>/node_modules/@smithy/middleware-serde/dist-cjs/index.js:35:20 at async /<作業ディレクトリパス>/node_modules/@smithy/core/dist-cjs/index.js:165:18 at async /<作業ディレクトリパス>/node_modules/@smithy/middleware-retry/dist-cjs/index.js:320:38 at async /<作業ディレクトリパス>/node_modules/@aws-sdk/middleware-logger/dist-cjs/index.js:34:22 at async getSSMParameter (/<作業ディレクトリパス>/node_modules/@aws/cloudfront-hosting-toolkit/bin/cli/utils/awsSDKUtil.js:499:26) at async getPipelineStatus (/<作業ディレクトリパス>/node_modules/@aws/cloudfront-hosting-toolkit/bin/cli/utils/awsSDKUtil.js:534:30) { '$fault': 'client', '$metadata': { httpStatusCode: 400, requestId: 'aaa09af6-7166-4b3d-9050-7f432ad57b05', extendedRequestId: undefined, cfId: undefined, attempts: 1, totalRetryDelay: 0 }, __type: 'AccessDeniedException' } AccessDeniedException: User: arn:aws:iam::<Assume Role元AWSアカウントID>:user/<IAMユーザー名> is not authorized to perform: ssm:GetParameter on resource: arn:aws:ssm:us-east-1:<Assume Role元AWSアカウントID>:parameter/hosting-main-cloudfront-hosting-toolkit-test-main/PipelineName with an explicit deny in an identity-based policy at throwDefaultError (/<作業ディレクトリパス>/node_modules/@smithy/smithy-client/dist-cjs/index.js:839:20) at /<作業ディレクトリパス>/node_modules/@smithy/smithy-client/dist-cjs/index.js:848:5 at de_CommandError (/<作業ディレクトリパス>/node_modules/@aws-sdk/client-ssm/dist-cjs/index.js:7003:14) at process.processTicksAndRejections (node:internal/process/task_queues:95:5) at async /<作業ディレクトリパス>/node_modules/@smithy/middleware-serde/dist-cjs/index.js:35:20 at async /<作業ディレクトリパス>/node_modules/@smithy/core/dist-cjs/index.js:165:18 at async /<作業ディレクトリパス>/node_modules/@smithy/middleware-retry/dist-cjs/index.js:320:38 at async /<作業ディレクトリパス>/node_modules/@aws-sdk/middleware-logger/dist-cjs/index.js:34:22 at async getSSMParameter (/<作業ディレクトリパス>/node_modules/@aws/cloudfront-hosting-toolkit/bin/cli/utils/awsSDKUtil.js:499:26) at async getPipelineStatus (/<作業ディレクトリパス>/node_modules/@aws/cloudfront-hosting-toolkit/bin/cli/utils/awsSDKUtil.js:534:30) { '$fault': 'client', '$metadata': { httpStatusCode: 400, requestId: 'aaa09af6-7166-4b3d-9050-7f432ad57b05', extendedRequestId: undefined, cfId: undefined, attempts: 1, totalRetryDelay: 0 }, __type: 'AccessDeniedException' }
ソースコードを確認したところ、プロファイルを引数として渡すことはできないようです。
#!/usr/bin/env node /* * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"). * You may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import { handleDeleteCommand } from "./actions/delete"; import handleDeployCommand from "./actions/deploy"; import { handleShowCommand } from "./actions/show"; import handleInitCommand from "./actions/init"; import { ERROR_PREFIX } from "./shared/constants"; import { handleStatusCommand } from "./actions/status"; const yargs = require("yargs"); async function main() { const args = yargs .usage("Usage: $0 <command> [options]") .command( "init", "Step by step guide for configuring a GitHub source code repository and generate a configuration file", (yargs: any) => { yargs .option("s3", { describe: "Step by step guide for configuring an S3 source code repository and generate a configuration file", type: "boolean", }) } ) .command( "deploy", 'Initiate a deployment of the infrastructure, utilizing the configuration file generated during the execution of the "init" command' ) .command( "show", "Show the domain name connected to the deployed source code repository for a website that has been deployed" ) .command( "delete", "Completely remove the hosting infrastructure from your AWS account" ) .command("status", "Display the current status of the pipeline deployment") .help() .parse(); if (args._.length > 1) { console.error(`${ERROR_PREFIX} Only one command at a time`); process.exit(1); } await handleCommand(args); } async function handleCommand({ _: [command], s3, }: { _: string[]; s3?: boolean; }) { switch (command) { case "deploy": await handleDeployCommand(); break; case "show": await handleShowCommand(); break; case "init": await handleInitCommand(s3 || false); break; case "delete": await handleDeleteCommand(); break; case "status": await handleStatusCommand(); break; default: yargs.showHelp() } } if (require.main === module) { main().catch((err) => { console.error(err); process.exit(1); }); }
Assume Role用スクリプトの実行
今までの挙動から判断するに、CloudFront Hosting ToolkitはAWS CLIのプロファイルを認識しないようです。
専用にアクセスキーを発行することはしたくはないので、Assume Roleするスクリプトを用意します。以下記事を参考にしました。
作成したAssume Role用のシェルスクリプトは以下のとおりです。
#!/usr/bin/env bash set -euo pipefail readonly AWS_CONFIG_FILE="${HOME}/.aws/config" readonly DEFAULT_REGION="us-east-1" readonly SESSION_DURATION=3600 # 使用方法の表示 function print_usage() { cat <<EOF Usage: $0 [-p PROFILE] [-t TOKEN_CODE] -p PROFILE AWS profile name in ${AWS_CONFIG_FILE} -t TOKEN_CODE MFA token code If no arguments are provided, the script will run in interactive mode. EOF } # プロファイル一覧の表示 function print_profile_list() { echo -e "\nProfile List:" grep "\[profile .*\]" "${AWS_CONFIG_FILE}" || echo "No profiles found" } # 指定された変数に標準入力結果を代入 function read_user_input() { local prompt="$1" local var_name="$2" read -p "${prompt}: " "${var_name}" } # プロファイル内の指定したキーの値を取得 function get_aws_config_value() { local key="$1" aws configure get "${key}" --profile "${PROFILE}" } # Assume Roleの実行 function assume_role() { local role_arn="$1" local serial_number="$2" local source_profile="$3" local token_code="$4" local session_name session_name="session-$(date +%s)" aws sts assume-role \ --role-arn "${role_arn}" \ --serial-number "${serial_number}" \ --role-session-name "${session_name}" \ --profile "${source_profile}" \ --duration-seconds "${SESSION_DURATION}" \ --token-code "${token_code}" } # Assume Role結果を環境変数に代入 function set_aws_environment_variables() { local assume_role_output="$1" export AWS_ACCESS_KEY_ID=$(echo "${assume_role_output}" | jq -r .Credentials.AccessKeyId) export AWS_SECRET_ACCESS_KEY=$(echo "${assume_role_output}" | jq -r .Credentials.SecretAccessKey) export AWS_SESSION_TOKEN=$(echo "${assume_role_output}" | jq -r .Credentials.SessionToken) } # メインで実行する関数 function main() { local PROFILE="" local TOKEN_CODE="" # 引数のパース while getopts ":p:t:h" opt; do case ${opt} in p) PROFILE=$OPTARG ;; t) TOKEN_CODE=$OPTARG ;; h) print_usage exit 0 ;; \?) echo "Invalid option: $OPTARG" 1>&2 print_usage exit 1 ;; :) echo "Invalid option: $OPTARG requires an argument" 1>&2 print_usage exit 1 ;; esac done shift $((OPTIND - 1)) # 引数でプロファイル名もしくはMFAトークンコードが入力されなかった場合は、対話形式で入力を受け付ける if [[ -z "$PROFILE" || -z "$TOKEN_CODE" ]]; then print_profile_list [ -z "$PROFILE" ] && read_user_input "Profile" PROFILE [ -z "$TOKEN_CODE" ] && read_user_input "MFA Code" TOKEN_CODE fi # 指定されたプロファイル名の情報を取得 local role_arn local serial_number local source_profile local region role_arn=$(get_aws_config_value "role_arn") serial_number=$(get_aws_config_value "mfa_serial") source_profile=$(get_aws_config_value "source_profile") region=$(get_aws_config_value "region") # Assume Roleの実行 local assume_role_output assume_role_output=$( assume_role \ "${role_arn}" \ "${serial_number}" \ "${source_profile}" \ "${TOKEN_CODE}" ) # Assume Roleの結果を環境変数に代入 set_aws_environment_variables "${assume_role_output}" # デフォルトリージョンの指定 export AWS_DEFAULT_REGION="${region:-${DEFAULT_REGION}}" echo "AWS_DEFAULT_REGION : ${AWS_DEFAULT_REGION}" # Assume Roleが正常に行われたか確認 aws sts get-caller-identity } main "$@"
参考にしたスクリプトは対話式でプロファイルやMFAトークンコードを入力していましたが、これらの情報をコマンドライン引数で渡せられるように機能追加をしました。
試してみましょう。
なお、私はfish shellを使用しており、source ../assume-role.sh
を実行しても環境変数がセットされません。対応としてbassを使ってシェルスクリプトを呼び出します。
$ bash ../assume-role.sh -h Usage: ../assume-role.sh [-p PROFILE] [-t TOKEN_CODE] -p PROFILE AWS profile name in /<ホームディレクトリ>/.aws/config -t TOKEN_CODE MFA token code If no arguments are provided, the script will run in interactive mode. $ bass source ../assume-role.sh -p <プロファイル名> -t <MFAトークンコード> AWS_DEFAULT_REGION : us-east-1 { "UserId": "<IAMユーザーID>:session-1719125569", "Account": "<Assume Role先AWSアカウントID>", "Arn": "arn:aws:sts::<Assume Role先AWSアカウントID>:assumed-role/<IAMロール名>/session-1719125569" } $ echo $AWS_SESSION_TOKEN IQoJb3JpZ2luX2VjEMr..(以下略)..
正常にAssume Roleでき、環境変数がセットされたようです。
CloudFront Hosting Toolkitを使ったデプロイ(2回目)
それではデプロイです。
$ npx cloudfront-hosting-toolkit deploy --> 1. Setting up a SSL/TLS certificate with AWS Certificate Manager (ACM) status=undefined A CNAME record has been added to your hosted zone. It may take a few minutes for the ACM service to validate your domain. Please wait for the validation process to complete. A CNAME record has been added to your hosted zone. It may take a few minutes for the ACM service to validate your domain. Please wait for the validation process to complete. Certificate is not ready to be used. Waiting ... . . (中略) . . Certificate is not ready to be used. Waiting ... Certificate is not ready to be used. Waiting ... The certificate is ready to be used. --> 2. Bootstrapping your AWS account Please wait ... | ████████████████████████████████████████ | 100% --> 3. Create resources for connecting your AWS account to your GitHub repository. Please wait ... | ████████████████████████████████████████ | 100% --> 4. Configure github connection You need to complete Github authentication using the AWS Console. To do so, follow these steps: 1. Open the following page: https://us-east-1.console.aws.amazon.com/codesuite/settings/connections 2. In the connection list, look out for connection name: cloudfront-hosting-toolkit-test- 3. For this connection with Status=Pending, complete the connection by following these instructions: - Select the pending connection cloudfront-hosting-toolkit-test-. - Click on Update a pending connection. - In the new popup window, under Github apps, choose an app installation, or create a new app by selecting Install a new app. - If you have already installed an app, select the app, click on Connect, and refresh the page if needed. The status of the connection should be Available. - If you choose to Install a new app, follow the on-screen instructions to authenticate your Github account, click on Connect, and refresh the page if needed. The status of the connection should be Available. ? Please complete the operation and type 'ok' to continue ›
GitHub連携をするように催促されました。
ちなみに、現時点で以下のようなログファイルが出力されていました。AWS CDKを内部的に実行していることがわかりますね。
══════════════════════ npx cdk bootstrap --context config-path=/<作業ディレクトリパス>/cloudfront-hosting-toolkit-test/cloudfront-hosting-toolkit --context certificate-arn=arn:aws:acm:us-east-1:<Assume Role先AWSアカウントID>:certificate/1c7238d4-0620-4327-b8ea-389f72b68bd9 ══════════════════════ ⏳ Bootstrapping environment aws://<Assume Role先AWSアカウントID>/us-east-1... Trusted accounts for deployment: (none) Trusted accounts for lookup: (none) Using default execution policy of 'arn:aws:iam::aws:policy/AdministratorAccess'. Pass '--cloudformation-execution-policies' to customize. CDKToolkit: creating CloudFormation changeset... CDKToolkit | 0/4 | 18:47:23 | UPDATE_IN_PROGRESS | AWS::IAM::Role | DeploymentActionRole CDKToolkit | 0/4 | 18:47:17 | UPDATE_IN_PROGRESS | AWS::CloudFormation::Stack | CDKToolkit User Initiated CDKToolkit | 0/4 | 18:47:21 | UPDATE_IN_PROGRESS | AWS::SSM::Parameter | CdkBootstrapVersion CDKToolkit | 1/4 | 18:47:21 | UPDATE_COMPLETE | AWS::SSM::Parameter | CdkBootstrapVersion CDKToolkit | 2/4 | 18:47:39 | UPDATE_COMPLETE | AWS::IAM::Role | DeploymentActionRole CDKToolkit | 3/4 | 18:47:41 | UPDATE_COMPLETE_CLEA | AWS::CloudFormation::Stack | CDKToolkit CDKToolkit | 4/4 | 18:47:42 | UPDATE_COMPLETE | AWS::CloudFormation::Stack | CDKToolkit ✅ Environment aws://<Assume Role先AWSアカウントID>/us-east-1 bootstrapped.
══════════════════════ npx cdk deploy hosting-connection-cloudfront-hosting-toolkit-test-main-non-97 --context config-path=/<作業ディレクトリパス>/cloudfront-hosting-toolkit-test/cloudfront-hosting-toolkit --context certificate-arn=arn:aws:acm:us-east-1:<Assume Role先AWSアカウントID>:certificate/1c7238d4-0620-4327-b8ea-389f72b68bd9 ══════════════════════ ✨ Synthesis time: 1.8s hosting-connection-cloudfront-hosting-toolkit-test-main-non-97: start: Building ebe9a8787caa48eb49bbe1c33dc994d46c6414a6a127b16df154acd2dbfa645a:<Assume Role先AWSアカウントID>-us-east-1 hosting-connection-cloudfront-hosting-toolkit-test-main-non-97: success: Built ebe9a8787caa48eb49bbe1c33dc994d46c6414a6a127b16df154acd2dbfa645a:<Assume Role先AWSアカウントID>-us-east-1 hosting-connection-cloudfront-hosting-toolkit-test-main-non-97: start: Publishing ebe9a8787caa48eb49bbe1c33dc994d46c6414a6a127b16df154acd2dbfa645a:<Assume Role先AWSアカウントID>-us-east-1 hosting-connection-cloudfront-hosting-toolkit-test-main-non-97: success: Published ebe9a8787caa48eb49bbe1c33dc994d46c6414a6a127b16df154acd2dbfa645a:<Assume Role先AWSアカウントID>-us-east-1 hosting-connection-cloudfront-hosting-toolkit-test-main-non-97: deploying... [1/1] hosting-connection-cloudfront-hosting-toolkit-test-main-non-97: creating CloudFormation changeset... hosting-connection-cloudfront-hosting-toolkit-test-main-non-97 | 1/6 | 18:48:19 | CREATE_COMPLETE | AWS::CloudFormation::Stack | hosting-connection-cloudfront-hosting-toolkit-test-main-non-97 hosting-connection-cloudfront-hosting-toolkit-test-main-non-97 | 1/6 | 18:48:05 | REVIEW_IN_PROGRESS | AWS::CloudFormation::Stack | hosting-connection-cloudfront-hosting-toolkit-test-main-non-97 User Initiated hosting-connection-cloudfront-hosting-toolkit-test-main-non-97 | 1/6 | 18:48:13 | CREATE_IN_PROGRESS | AWS::CloudFormation::Stack | hosting-connection-cloudfront-hosting-toolkit-test-main-non-97 User Initiated hosting-connection-cloudfront-hosting-toolkit-test-main-non-97 | 1/6 | 18:48:15 | CREATE_IN_PROGRESS | AWS::SSM::Parameter | RepositoryConnection/SSMConnectionRegion (RepositoryConnectionSSMConnectionRegion4029CE52) hosting-connection-cloudfront-hosting-toolkit-test-main-non-97 | 1/6 | 18:48:15 | CREATE_IN_PROGRESS | AWS::SSM::Parameter | RepositoryConnection/SSMConnectionName (RepositoryConnectionSSMConnectionNameAB648C27) hosting-connection-cloudfront-hosting-toolkit-test-main-non-97 | 1/6 | 18:48:15 | CREATE_IN_PROGRESS | AWS::CodeStarConnections::Connection | RepositoryConnection/MyCfnConnectioncloudfront-hosting-toolkit-test (RepositoryConnectionMyCfnConnectioncloudfronthostingtoolkittest6BB0B6C0) hosting-connection-cloudfront-hosting-toolkit-test-main-non-97 | 1/6 | 18:48:15 | CREATE_IN_PROGRESS | AWS::CDK::Metadata | CDKMetadata/Default (CDKMetadata) hosting-connection-cloudfront-hosting-toolkit-test-main-non-97 | 1/6 | 18:48:16 | CREATE_IN_PROGRESS | AWS::CodeStarConnections::Connection | RepositoryConnection/MyCfnConnectioncloudfront-hosting-toolkit-test (RepositoryConnectionMyCfnConnectioncloudfronthostingtoolkittest6BB0B6C0) Resource creation Initiated hosting-connection-cloudfront-hosting-toolkit-test-main-non-97 | 1/6 | 18:48:16 | CREATE_IN_PROGRESS | AWS::SSM::Parameter | RepositoryConnection/SSMConnectionName (RepositoryConnectionSSMConnectionNameAB648C27) Resource creation Initiated hosting-connection-cloudfront-hosting-toolkit-test-main-non-97 | 1/6 | 18:48:16 | CREATE_IN_PROGRESS | AWS::SSM::Parameter | RepositoryConnection/SSMConnectionRegion (RepositoryConnectionSSMConnectionRegion4029CE52) Resource creation Initiated hosting-connection-cloudfront-hosting-toolkit-test-main-non-97 | 2/6 | 18:48:16 | CREATE_COMPLETE | AWS::CodeStarConnections::Connection | RepositoryConnection/MyCfnConnectioncloudfront-hosting-toolkit-test (RepositoryConnectionMyCfnConnectioncloudfronthostingtoolkittest6BB0B6C0) hosting-connection-cloudfront-hosting-toolkit-test-main-non-97 | 2/6 | 18:48:16 | CREATE_IN_PROGRESS | AWS::CDK::Metadata | CDKMetadata/Default (CDKMetadata) Resource creation Initiated hosting-connection-cloudfront-hosting-toolkit-test-main-non-97 | 3/6 | 18:48:16 | CREATE_COMPLETE | AWS::SSM::Parameter | RepositoryConnection/SSMConnectionName (RepositoryConnectionSSMConnectionNameAB648C27) hosting-connection-cloudfront-hosting-toolkit-test-main-non-97 | 4/6 | 18:48:16 | CREATE_COMPLETE | AWS::SSM::Parameter | RepositoryConnection/SSMConnectionRegion (RepositoryConnectionSSMConnectionRegion4029CE52) hosting-connection-cloudfront-hosting-toolkit-test-main-non-97 | 5/6 | 18:48:16 | CREATE_COMPLETE | AWS::CDK::Metadata | CDKMetadata/Default (CDKMetadata) hosting-connection-cloudfront-hosting-toolkit-test-main-non-97 | 5/6 | 18:48:17 | CREATE_IN_PROGRESS | AWS::SSM::Parameter | RepositoryConnection/SSMConnectionArn (RepositoryConnectionSSMConnectionArn1E74102B) hosting-connection-cloudfront-hosting-toolkit-test-main-non-97 | 5/6 | 18:48:18 | CREATE_IN_PROGRESS | AWS::SSM::Parameter | RepositoryConnection/SSMConnectionArn (RepositoryConnectionSSMConnectionArn1E74102B) Resource creation Initiated hosting-connection-cloudfront-hosting-toolkit-test-main-non-97 | 6/6 | 18:48:18 | CREATE_COMPLETE | AWS::SSM::Parameter | RepositoryConnection/SSMConnectionArn (RepositoryConnectionSSMConnectionArn1E74102B) ✅ hosting-connection-cloudfront-hosting-toolkit-test-main-non-97 ✨ Deployment time: 18.76s Outputs: hosting-connection-cloudfront-hosting-toolkit-test-main-non-97.ExportsOutputFnGetAttRepositoryConnectionMyCfnConnectioncloudfronthostingtoolkittest6BB0B6C0ConnectionArnC6089F79 = arn:aws:codestar-connections:us-east-1:<Assume Role先AWSアカウントID>:connection/aeca0b6c-87a0-4f45-b2b2-6ad39e0648fa hosting-connection-cloudfront-hosting-toolkit-test-main-non-97.RepositoryConnectionConnectionArn087CB8E2 = arn:aws:codestar-connections:us-east-1:<Assume Role先AWSアカウントID>:connection/aeca0b6c-87a0-4f45-b2b2-6ad39e0648fa hosting-connection-cloudfront-hosting-toolkit-test-main-non-97.RepositoryConnectionConnectionNameFD2EABB9 = cloudfront-hosting-toolkit-test- hosting-connection-cloudfront-hosting-toolkit-test-main-non-97.RepositoryConnectionHostingRegion1B4A18AD = us-east-1 Stack ARN: ✨ Total time: 20.56s arn:aws:cloudformation:us-east-1:<Assume Role先AWSアカウントID>:stack/hosting-connection-cloudfront-hosting-toolkit-test-main-non-97/85e351c0-307c-11ef-b1e6-0ecb10ce0993
また、この時点で証明書が作成されていました。CloudFormationのスタックを作成する際のログにはACMが含まれていないので、こちらはCloudFormationで管理されていないようです。
GitHubへの接続はステータスが保留中
になっていました。
以下記事を参考にGitHub連携をします。
保留中の接続を更新
をクリックすると、権限確認を促されるのでAuthorize AWS Connector for GitHub
をクリックします。
新しいアプリをインストールする
をクリックします。
インストール先を選択します。
インストールが完了したら、連携するリポジトリを選択してSave
をクリックします。
AWSマネジメントコンソールに戻ってGitHubアプリのIDを選択し、接続
をクリックします。
正常に連携が完了しました。
デプロイを実行します。
✔ Please complete the operation and type 'ok' to continue … ok --> 5. Deploy the hosting infrastructure within your AWS account Please wait while deploying the infrastructure, it may take a few minutes. Please wait ... | ████████████████████████████████████████ | 100% _____________________________________________________________________ The Origin paired with its associated CloudFront domain name: > Code Repository: https://github.com/non-97/cloudfront-hosting-toolkit-test.git > Hosting: https://d3kt1ccx65w6km.cloudfront.net ? Would you like to associate the domain name to the CloudFront distribution automatically now, or would you prefer to do it later? › - Use arrow-keys. Return to submit. ❯ Associate automatically now. Do it later.
CloudFrontの作成が完了したようです。OACでオリジンも設定されており、ビヘイビアでパスパターンごとにキャッシュポリシーやレスポンスヘッダーポリシーを細かく設定しているようです。
作成されたリソースの全容は以下のとおりです。
ただし、現時点ではCloudFrontディストリビューションへのAliasレコードは登録されていないようです。
Associate automatically now.
を選択して、Aliasレコードを登録させます。
✔ Would you like to associate the domain name to the CloudFront distribution automatically now, or would you prefer to do it later? › Associate automatically now. A new A Record has been added/updated to your DNS records that points to your CloudFront distribution: > cf-test.non-97.net -> d3kt1ccx65w6km.cloudfront.net It may take a few minutes to reflect the change. In the future, whenever you push changes to your Github repository, an automatic pipeline will be triggered to deploy the new version. _____________________________________________________________________ The hosting infrastructure for your project has been successfully deployed on your AWS account The deployment consists of the following AWS CloudFormation stack(s): > hosting-connection-cloudfront-hosting-toolkit-test-main-non-97 > hosting-main-cloudfront-hosting-toolkit-test-main The following AWS CodePipeline has been created for automatic deployment upon Git push execution: > non-97-cloudfront-hosting-toolkit-test You can review the resources deployed by logging into the AWS Management Console at https://aws.amazon.com/console The pipeline has been initiated following the recent deployment to apply any changes made. The pipeline is in progress, waiting for the pipeline to finish... Please wait ... | ████████████████████████████████████████ | 100% *** ERROR *** The pipeline execution encountered an error on the stage 'ChangeUri'. To investigate and resolve the issue, please follow these steps: A. Explore our troubleshooting section https://github.com/awslabs/cloudfront-hosting-toolkit/blob/main/docs/troubleshooting.md B. Inspect the pipeline execution details 1. Visit the AWS Management Console. 2. Navigate to AWS CodePipeline. 3. Select the "non-97-cloudfront-hosting-toolkit-test" pipeline. 4. Inspect the pipeline execution details and logs for error messages. 5. Take the necessary actions to address the error. 6. Once resolved, you can trigger a new pipeline execution by choosing 'Release change' on the AWS Console.
どうやらコンテンツのパイプラインでChangeUri
が失敗しているようです。
CodePipelineを確認すると、確かに失敗していました。
こちらの影響で、アクセスをしてもPlease note that your are currently seeing this screen because this is the first deployment of the website. So, just take it easy and unwind, the page will automatically refresh on its own.
と表示されてしまいます。
CodePipelineのChangeUri
呼び出し先のStep Functionsを確認すると、Update KeyValueStore
が失敗しています。
ログは以下のとおりです。呼び出し先のLambda関数上でAWS CRTライブラリが見つからないようです。
{ "errorType": "Error", "errorMessage": "AWS CRT binary not present in any of the following locations:\n\t/opt/nodejs/node_modules/aws-crt/dist/bin/linux-x64-glibc/aws-crt-nodejs.node", "trace": [ "Error: AWS CRT binary not present in any of the following locations:", "\t/opt/nodejs/node_modules/aws-crt/dist/bin/linux-x64-glibc/aws-crt-nodejs.node", " at Object.<anonymous> (/opt/nodejs/node_modules/aws-crt/dist/native/binding.js:109:11)", " at Module._compile (node:internal/modules/cjs/loader:1358:14)", " at Module._extensions..js (node:internal/modules/cjs/loader:1416:10)", " at Module.load (node:internal/modules/cjs/loader:1208:32)", " at Module._load (node:internal/modules/cjs/loader:1024:12)", " at Module.require (node:internal/modules/cjs/loader:1233:19)", " at require (node:internal/modules/helpers:179:18)", " at Object.<anonymous> (/opt/nodejs/node_modules/aws-crt/dist/native/auth.js:20:35)", " at Module._compile (node:internal/modules/cjs/loader:1358:14)", " at Module._extensions..js (node:internal/modules/cjs/loader:1416:10)" ] }
こちらのLambda関数にはHostingPipelineInfrastructureUpdateCFFAwsSdkLayerEA1E386E
がアタッチされていました。
こちらでのLambda Layerは../lambda/layers/aws_sdk`をバンドルしているようです。
const awsSdkLayer = new lambda.LayerVersion(this, "AwsSdkLayer", { compatibleRuntimes: [lambda.Runtime.NODEJS_20_X], code: lambda.Code.fromAsset(path.join(__dirname, "../lambda/layers/aws_sdk")), description: "AWS SDK lib including client-cloudfront-keyvaluestore", });
package.jsonにはAWS CRTは含まれていそうです。
{ "name": "AWS_SDK_Layer", "version": "1.0.0", "description": "Latest AWS SDK libs", "main": "", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "dependencies": { "@aws-sdk/client-cloudfront-keyvaluestore": "^3.511.0", "@aws-sdk/signature-v4-crt": "^3.511.0", "@aws-sdk/signature-v4-multi-region": "^3.511.0" }, "author": { "name": "Amazon Web Services", "url": "https://aws.amazon.com/solutions" }, "license": "Apache-2.0" }
Lambda Layerをダウンロードしてきて解凍したディレクトリを確認します。
$ ls -l ../../HostingPipelineInfrastructureUpdateCFFAwsSdkLayerEA1E386E-081b2836-9d7c-46e9-9a03-247c1db1bf74/nodejs/node_modules/aws-crt/ total 8 drwxr-xr-x@ 6 <ユーザー名> staff 192 6 22 19:47 dist/ drwxr-xr-x@ 6 <ユーザー名> staff 192 6 22 19:47 dist.browser/ drwxr-xr-x@ 3 <ユーザー名> staff 96 6 22 19:45 lib/ -rw-r--r--@ 1 <ユーザー名> staff 1999 1 1 1980 package.json drwxr-xr-x@ 7 <ユーザー名> staff 224 6 22 19:45 scripts/ $ ls -l ../../HostingPipelineInfrastructureUpdateCFFAwsSdkLayerEA1E386E-081b2836-9d7c-46e9-9a03-247c1db1bf74/nodejs/node_modules/aws-crt/dist/ total 8 drwxr-xr-x@ 18 <ユーザー名> staff 576 6 22 19:45 common/ -rw-r--r--@ 1 <ユーザー名> staff 2948 1 1 1980 index.js drwxr-xr-x@ 19 <ユーザー名> staff 608 6 22 19:45 native/
確かにエラーログで出力されていたnodejs/node_modules/aws-crt/dist/bin/linux-x64-glibc/aws-crt-nodejs.node
は見つかりません。
CloudFront Hosting Toolkitをグローバルインストールをして再デプロイ
もしかして、CloudFront Hosting Toolkitをグローバルインストールではなく、ローカルインストールで使用しているためでしょうか。
CloudFront Hosting Toolkitをグローバルインストールをして再デプロイします。
グローバルインストールします。
$ npm install -g @aws/cloudfront-hosting-toolkit npm WARN deprecated inflight@1.0.6: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. npm WARN deprecated glob@7.2.3: Glob versions prior to v9 are no longer supported npm WARN deprecated @aws-sdk/config-resolver@3.374.0: This package has moved to @smithy/config-resolver npm WARN deprecated @aws-sdk/node-config-provider@3.374.0: This package has moved to @smithy/node-config-provider added 310 packages in 25s 26 packages are looking for funding run `npm fund` for details
デプロイします。
cloudfront-hosting-toolkit deploy --> 1. Setting up a SSL/TLS certificate with AWS Certificate Manager (ACM) status=ISSUED The certificate for this domain has already been created. The certificate is ready to be used. --> 2. Bootstrapping your AWS account Please wait ... | ████████████████████████████████████████ | 100% --> 3. Create resources for connecting your AWS account to your GitHub repository. Please wait ... | ████████████████████████████████████████ | 100% --> 4. Deploy the hosting infrastructure within your AWS account Please wait while deploying the infrastructure, it may take a few minutes. Please wait ... | ████████████████████████████████████████ | 100% _____________________________________________________________________ The Origin paired with its associated CloudFront domain name: > Code Repository: https://github.com/non-97/cloudfront-hosting-toolkit-test.git > Hosting: https://d3kt1ccx65w6km.cloudfront.net > Domain name 'cf-test.non-97.net' is already associated with the CloudFront distribution. In the future, whenever you push changes to your Github repository, an automatic pipeline will be triggered to deploy the new version. _____________________________________________________________________ The hosting infrastructure for your project has been successfully deployed on your AWS account The deployment consists of the following AWS CloudFormation stack(s): > hosting-connection-cloudfront-hosting-toolkit-test-main-non-97 > hosting-main-cloudfront-hosting-toolkit-test-main The following AWS CodePipeline has been created for automatic deployment upon Git push execution: > non-97-cloudfront-hosting-toolkit-test You can review the resources deployed by logging into the AWS Management Console at https://aws.amazon.com/console The pipeline has been initiated following the recent deployment to apply any changes made. The pipeline is in progress, waiting for the pipeline to finish... Please wait ... | ████████████████████████████████████████ | 100% Current pipeline status: Succeeded
今度は最後までデプロイが完了しました。グローバルインストールしたものを使っても、参照するのはカレントディレクトリの./cloudfront-hosting-toolkit
配下の設定ファイルを参照するためか別スタックでのデプロイではないようです。
デプロイ時のイベントを確認すると、Requested update requires the creation of a new physical resource; hence creating one.
とLambda Layerが新しく作られるようです。
前回失敗していたCodePipelineを確認すると、最後まで正常に実行が完了しています。
先ほど失敗していたLambda関数も正常に実行完了しています。
INIT_START Runtime Version: nodejs:20.v23 Runtime Version ARN: arn:aws:lambda:us-east-1::runtime:92c5bcb1529200756eb64a0d90d4ab606fdaf21421321da6c202187b88833f52 START RequestId: 71567e55-f1e1-49b3-bf9c-c213298e06c9 Version: $LATEST 2024-06-23T07:21:47.751Z 71567e55-f1e1-49b3-bf9c-c213298e06c9 INFO event= { "commitId": "a680b14f8cefc6aacd2c6a4b07e8a4edf108bae6" } 2024-06-23T07:21:47.754Z 71567e55-f1e1-49b3-bf9c-c213298e06c9 INFO Get ETAG for KVS arn:aws:cloudfront::<Assume Role先AWSアカウントID>:key-value-store/a8423ea3-4665-4cb4-bf70-a0bc3f85fa47 2024-06-23T07:21:48.038Z 71567e55-f1e1-49b3-bf9c-c213298e06c9 INFO Update KVS using ETAG KVTVPDKIKX0DER 2024-06-23T07:21:48.193Z 71567e55-f1e1-49b3-bf9c-c213298e06c9 INFO KVS updated END RequestId: 71567e55-f1e1-49b3-bf9c-c213298e06c9 REPORT RequestId: 71567e55-f1e1-49b3-bf9c-c213298e06c9 Duration: 445.30 ms Billed Duration: 446 ms Memory Size: 512 MB Max Memory Used: 93 MB Init Duration: 400.97 ms
試しにアクセスします。
$ curl https://cf-test.non-97.net/README.md # cloudfront-hosting-toolkit-test
正常にアクセスできました。
その他、cloudfront-hosting-toolkit
コマンドで確認できる情報は以下のとおりです。
$ cloudfront-hosting-toolkit show The Origin paired with its associated CloudFront domain name: Code Repository: https://github.com/non-97/cloudfront-hosting-toolkit-test.git/main --> Hosting: https://d3kt1ccx65w6km.cloudfront.net cf-test.non-97.net --> Hosting: d3kt1ccx65w6km.cloudfront.net $ cloudfront-hosting-toolkit status Current pipeline status: Succeeded
GitにコンテンツをPush
GitにコンテンツをPushしてコンテンツがデプロイされるかどうか確認します。
適当にファイルを用意してPushします。
$ git add . $ git ls-files .gitignore README.md dir/index.html index.html test.html $ git commit -m "cloudfront-hosting-toolkitのCI/CDパイプラインの動作確認のため適当にファイルを追加" [main 3d54ae9] cloudfront-hosting-toolkitのCI/CDパイプラインの動作確認のため適当にファイルを追加 4 files changed, 200 insertions(+) create mode 100644 .gitignore create mode 100644 dir/index.html create mode 100644 index.html create mode 100644 test.html $ git push Enumerating objects: 8, done. Counting objects: 100% (8/8), done. Delta compression using up to 10 threads Compressing objects: 100% (3/3), done. Writing objects: 100% (7/7), 1.99 KiB | 1.99 MiB/s, done. Total 7 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0) To https://github.com/non-97/cloudfront-hosting-toolkit-test.git a680b14..3d54ae9 main -> main
すると、パイプラインが起動して正常に完了していました。
コンテンツを保存しているS3バケットを確認します。コミットIDのディレクトリが作成されており、中にはコンテンツが保存されていました。
初回デプロイ時に存在していたコンテンツは、最新のデプロイのタイミングで削除されるようです。
INIT_START Runtime Version: nodejs:18.v29 Runtime Version ARN: arn:aws:lambda:us-east-1::runtime:5c2d7f0b914a9dbb8b6a6e3117c7950fa2b7434331c349799226fadd052f19a9 START RequestId: bd15acf8-a7f7-46ae-b0dc-f8624b6fdcc4 Version: $LATEST 2024-06-23T07:40:38.594Z bd15acf8-a7f7-46ae-b0dc-f8624b6fdcc4 INFO event= { "commitId": "3d54ae90e02c21fc236e7790f779226c79d6ed18" } 2024-06-23T07:40:39.858Z bd15acf8-a7f7-46ae-b0dc-f8624b6fdcc4 INFO Deleted file: a680b14f8cefc6aacd2c6a4b07e8a4edf108bae6/README.md 2024-06-23T07:40:39.858Z bd15acf8-a7f7-46ae-b0dc-f8624b6fdcc4 INFO Deleted 1 objects successfully. END RequestId: bd15acf8-a7f7-46ae-b0dc-f8624b6fdcc4 REPORT RequestId: bd15acf8-a7f7-46ae-b0dc-f8624b6fdcc4 Duration: 1285.37 ms Billed Duration: 1286 ms Memory Size: 128 MB Max Memory Used: 90 MB Init Duration: 381.72 ms
実際にアクセスしましょう。
$ curl https://cf-test.non-97.net/README.md # cloudfront-hosting-toolkit-test $ curl https://cf-test.non-97.net/ index.html $ curl https://cf-test.non-97.net/test.html test.html $ curl https://cf-test.non-97.net/dir/ dir/index.html $ curl https://cf-test.non-97.net/dir/ -I HTTP/2 200 date: Sun, 23 Jun 2024 07:51:39 GMT content-type: text/html content-length: 15 last-modified: Sun, 23 Jun 2024 07:40:27 GMT etag: "bdf7745a2f17049b4a445c5a088e1fda" x-amz-server-side-encryption: AES256 accept-ranges: bytes server: AmazonS3 x-cache: Hit from cloudfront via: 1.1 a4ab9ca675174fa667c8399f24cb4440.cloudfront.net (CloudFront) x-amz-cf-pop: NRT12-P2 alt-svc: h3=":443"; ma=86400 x-amz-cf-id: FRCGNlVMuFh0GsIiquipydye50cEmsWmyYgNuFPziw48dpiWbJyIAA== x-xss-protection: 1; mode=block x-frame-options: DENY referrer-policy: strict-origin-when-cross-origin x-content-type-options: nosniff strict-transport-security: max-age=31536000; includeSubDomains $ curl https://cf-test.non-97.net/dir/ -I HTTP/2 200 date: Sun, 23 Jun 2024 07:51:43 GMT content-type: text/html content-length: 15 last-modified: Sun, 23 Jun 2024 07:40:27 GMT etag: "bdf7745a2f17049b4a445c5a088e1fda" x-amz-server-side-encryption: AES256 accept-ranges: bytes server: AmazonS3 x-cache: Hit from cloudfront via: 1.1 3c3704d1d972509b35eb599b7ec5b18e.cloudfront.net (CloudFront) x-amz-cf-pop: NRT12-P2 alt-svc: h3=":443"; ma=86400 x-amz-cf-id: uI2poobRk_X_dufm0vUYm46uYjNHBfoHnj9RSRYuJwTdIBwen4MWNg== x-xss-protection: 1; mode=block x-frame-options: DENY referrer-policy: strict-origin-when-cross-origin x-content-type-options: nosniff strict-transport-security: max-age=31536000; includeSubDomains $ curl https://cf-test.non-97.net/.gitignore <?xml version="1.0" encoding="UTF-8"?> <Error><Code>AccessDenied</Code><Message>Access Denied</Message><RequestId>MAY2Z458MFMACCCF</RequestId><HostId>q0kpOR+we6uBy7fv7+ZvNrDt69++HGmIQfajnRknb9xmtldZq7cLijzqiuWym4BEZp6v/k54lv4YStJ+AEK8DYhXt1eG1cxaQK6uSxnv/+I=</HostId></Error> $ curl https://cf-test.non-97.net/.gitignore -I HTTP/2 403 date: Wed, 26 Jun 2024 04:49:00 GMT content-type: application/xml server: AmazonS3 x-cache: Error from cloudfront via: 1.1 5519434325290aca21702ef9e3fa5194.cloudfront.net (CloudFront) x-amz-cf-pop: NRT12-P2 alt-svc: h3=":443"; ma=86400 x-amz-cf-id: Ud9kYAqDyWm4hwtPS57yQtRxr84ECexh0uqdS1jFkLWZwh0wU5P2iA== x-xss-protection: 1; mode=block x-frame-options: DENY referrer-policy: strict-origin-when-cross-origin x-content-type-options: nosniff strict-transport-security: max-age=31536000; includeSubDomains
コンテンツが反映されていますね。CloudFront Functionsを使ったディレクトリインデックスも正常に動作しています。
なお、.gitignore
についてはS3バケット上に展開されていないため、アクセスはできませんでした。
サクッと静的Webサイトを用意したい場合に
CloudFront Hosting Toolkitを使って静的Webサイト環境を作ってみました。
CodePipeline周りやコンテンツを切り替える処理を自作しようとすると結構大変です。サクッと静的Webサイトを用意したい場合に非常に使いやすそうですね。
なお、デプロイされるCodePipelineはV1です。モノレポでありファイルパスのトリガーを使いたいという場合にはCodePipeline V2に変更してあげましょう。
この記事が誰かの助けになれば幸いです。
以上、AWS事業本部 コンサルティング部の のんピ(@non____97)でした!